//
// Created by none98 on 2021/9/10.
//

#include <spdlog/spdlog.h>
#include "EventLoop.h"
#include "Selector.h"
#include "Timer.h"
#include "TimerEventQueue.h"
#include "Channel.h"

EventLoop::EventLoop():
    selector(new Selector),
    timerQueue(new TimerEventQueue)
{

}

void EventLoop::StartLoop() {
    while(true){
        activeChannels=std::move(selector->Select(timeout));
        //spdlog::info("active channels: {}",activeChannels.size());
        //then handle channel events
        if(activeChannels.size()>0){
            for(auto channel : activeChannels){
                channel->HandleEvents();
            }
        }
        //handle timer events
        std::vector<TimerCallBack> events = std::move(timerQueue->GetExpiredEvents(TimeStamp::NowTime()));
        for(auto i : events)
            i();
        events.clear();
        HandleTasks();
    }
}

long EventLoop::AddTimer(const Timer &timer) {
    return timerQueue->AddTimer(timer);
}

void EventLoop::CancelTimerBySeq(long seq) {
    timerQueue->CancelTimerBySequence(seq);
}

void EventLoop::CancelTimerByfd(int fd) {
    timerQueue->CancelTimerByFd(fd);
}

void EventLoop::AddTask(const std::function<void()> &task) {
    std::unique_lock<std::mutex> lock(taskQueueMutex);
    taskQueue.push_back(task);
}

void EventLoop::HandleTasks() {
    std::unique_lock<std::mutex> lock(taskQueueMutex);
    for(auto task : taskQueue){
        task();
    }
    taskQueue.clear();
}
